package demo.java.jvm;

/**
 * <h1>JVM</h1> JVM内存永久区已经被metaspace替换（JEP 122）。JVM参数 -XX:PermSize 和
 * –XX:MaxPermSize被XX:MetaSpaceSize 和 -XX:MaxMetaspaceSize代替。
 * 
 * 
 * <h2>JVM 内存划分：</h2>
 * 
 * 
 * <h2>类似-Xms、-Xmn 这些参数的含义：</h2>
 * <li>-Dfile.encoding=UTF-8
 * <li>-Xms20m -Xmx20m ##设置堆大小20m，并将最小和最大值设置相等，避免扩展
 * <li>-XX:+HeapDumpOnOutOfMemoryError ##dump出当前的内存堆转储快照
 * <li>-XX:HeapDumpPath=E:\job ##指定路径(转储文件还是挺大的)
 * <li>-XX:SurvivorRatio=8 ## 存活比2:8
 * 
 * 
 * <h3>堆内存分配：</h3>
 * <li>JVM 初始分配的内存由-Xms 指定，默认是物理内存的 1/64；
 * <li>JVM 最大分配的内存由-Xmx 指定，默认是物理内存的 1/4；
 * <li>默认空余堆内存小于 40% 时，JVM 就会增大堆直到-Xmx 的最大限制；空余堆内存大于 70% 时，JVM 会减少堆直到 -Xms
 * 的最小限制；
 * <li>因此服务器一般设置-Xms、-Xmx 相等以避免在每次 GC 后调整堆的大小。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。
 * 
 * <h3>非堆内存分配：</h3>
 * <li>JVM 使用-XX:PermSize 设置非堆内存初始值，默认是物理内存的 1/64；
 * <li>由 XX:MaxPermSize 设置最大非堆内存的大小，默认是物理内存的 1/4；
 * <li>-Xmn2G：设置年轻代大小为 2G；
 * <li>-XX:SurvivorRatio，设置年轻代中 Eden 区与 Survivor 区的比值。
 * 
 * JVM服务问题排查
 * 
 * 线上的服务就像一个黑匣子，具体什么情况，这个就是体现监控运维的价值，监控报警运维解决了的软件服务最后一公里的问题。大公司一般都有很成熟的监控服务系统，可视化服务状态，自动化运维操作，这些自动化的工具对开发人员来说都是如沐春风，但是一般中小企业这些基础建设就没有那么优秀了，很多问题都需要开发人员自行定位解决。
 * 线上的JVM服务运行久了或者出现访问压力时，服务往往会暴露一些问题，这个时候就需要开发人员自行定位具体问题，OpenJDK也提供了一些基本工具，比如
 * jstat：查询到每个堆分代的内存占用情况和Young GC和Full GC次数和时间
 * <li>jstack：定位java 栈问题 eg: jstack –l 23561
 * <li>查看栈信息 jmap：定位java heap问题,eg:jstat -gcutil ${pid} 1000 10 1. jmap -histo
 * ${pid} 查看实例内存 2. jmap -histo ${pid} | grep ${package} 查看包内存 3. jmap
 * -dump:format=b,file=文件名 [pid] 生产dump文件 4.jmap -heap ${pid} 查看堆信息
 * 
 * jps：查看容器进程 jinfo：jinfo ${pid} 查看java进程的详细信息
 * 
 * 对于JVM服务可能出现的问题，我们一般依次排查内容为：一般分四步排查 （1）. 宿主机器问题 （2）. 排查日志，检查程序代码 （3）.
 * JVM内存，是否频繁GC （4）. 线程栈，是否线程暴涨，线程死锁
 * 
 * 
 * 线上问题排查命令----JVM篇 https://blog.csdn.net/u010827436/article/details/46564641
 *
 */
public interface JavaVirtualMachine {
    /**
     * <li>非堆内存:方法区（线程共享）：常量、静态变量、JIT(即时编译器) 编译后的代码也都在方法区；
     * <li>堆内存（线程共享）：垃圾回收的主要场所；
     * <li>程序计数器： 当前线程执行的字节码的位置指示器；
     * <li>虚拟机栈（栈内存）：保存局部变量、基本数据类型变量以及堆内存中某个对象的引用变量；
     * <li>本地方法栈 ：为 JVM 提供使用 native 方法的服务。
     */
    void 内存划分();

    /**
     * <h2>引用计数 ：</h2>原理是此对象有一个引用，即增加一个计数，删除一个引用则减少一个计数。垃圾回收时，只用收集计数为 0
     * 的对象。此算法最致命的是无法处理循环引用的问题；
     * 
     * <h2>标记-清除 ：</h2>此算法执行分两阶段。第一阶段从引用根节点开始标记所有被引用的对象，第二阶段遍历整个堆，把未标记的对象清除；
     * 此算法需要暂停整个应用，同时，会产生内存碎片；
     * 
     * <h2>复制算法
     * ：</h2>此算法把内存空间划为两个相等的区域，每次只使用其中一个区域。垃圾回收时，遍历当前使用区域，把正在使用中的对象复制到另外一个区域中；
     * 此算法每次只处理正在使用中的对象，因此复制成本比较小，同时复制过去以后还能进行相应的内存整理，不会出现 “碎片”
     * 问题。当然，此算法的缺点也是很明显的，就是需要两倍内存空间；
     * 
     * <h2>标记-整理 ：</h2>此算法结合了 “标记-清除” 和 “复制”
     * 两个算法的优点。也是分两阶段，第一阶段从根节点开始标记所有被引用对象，第二阶段遍历整个堆，把清除未标记对象并且把存活对象 “压缩”
     * 到堆的其中一块，按顺序排放。 此算法避免了 “标记-清除” 的碎片问题，同时也避免了 “复制” 算法的空间问题。
     */
    void 垃圾回收算法();

    /**
     * <pre>
    java 
    -server 
    -Djava.net.preferIPv4Stack=true 
    -Xms1000M                       //设置堆的初始大小
    -Xmx1000M 
    -XX:MetaspaceSize=300M 
    -XX:MaxMetaspaceSize=300M 
    -XX:SurvivorRatio=8 
    -XX:+UseBiasedLocking 
    -XX:+AggressiveOpts 
    -XX:+UseG1GC 
    -XX:+HeapDumpOnOutOfMemoryError 
    -XX:HeapDumpPath=/logs/gc_logs/ 
    -Xloggc:/logs/gc_logs/feature-bone-provider_gc.log 
    -XX:+UseGCLogFileRotation 
    -XX:NumberOfGCLogFiles=3 
    -XX:GCLogFileSize=128M 
    -XX:+PrintGC 
    -XX:+PrintGCDetails 
    -XX:+PrintGCTimeStamps 
    -XX:+PrintTenuringDistribution 
    -Dspring.profiles.active=t2 
    -javaagent:skywalking-agent.jar 
    -Dskywalking.agent.application_code=T2-feature-bone-provider.jar 
    -jar feature-bone-provider.jar 
    --server.address=172.16.0.143 
    --server.port=10078
     * </pre>
     * 
     * <pre>
     * java 
    -Xms1024m 
    -Xmx1024m 
    -Xmn512m 
    -Xss256k 
    -XX:SurvivorRatio=4 
    -XX:MaxTenuringThreshold=15 
    -javaagent:$currentdir/lib/aspectjweaver-1.7.3.jar 
    -Djava.ext.dirs=$currentdir/lib:config 
    com.ximalaya.xdcs.report.redis.RedisInfoTask
     * </pre>
     * 
     * <pre>
     * java 
     * -Xms6144m 
     * -Xmx6144m 
     * -Xmn2g 
     * -XX:PermSize=512M 
     * -XX:MaxPermSize=512M 
     * -XX:+UseConcMarkSweepGC 
     * -XX:+UseParNewGC 
     * -XX:+DisableExplicitGC 
     * -XX:+CMSParallelRemarkEnabled 
     * -XX:+CMSClassUnloadingEnabled 
     * -XX:+CMSPermGenSweepingEnabled 
     * -XX:CMSInitiatingOccupancyFraction=80 
     * -XX:CMSFullGCsBeforeCompaction=5 
     * -XX:+UseCMSCompactAtFullCollection 
     * -XX:+CMSScavengeBeforeRemark 
     * -XX:+HeapDumpOnOutOfMemoryError 
     * -Xloggc:/var/log/xdcs-alert/gc.log 
     * -XX:+PrintGCDetails 
     * -XX:+PrintGCDateStamps 
     * -XX:+PrintGCApplicationStoppedTime 
     * -XX:+PrintGCApplicationConcurrentTime 
     * -XX:+CMSConcurrentMTEnabled 
     * -XX:+ExplicitGCInvokesConcurrent 
     * -XX:HeapDumpPath=/var/log/xdcs-alert/xdcs-alert.hprof 
     * -javaagent:$currentdir/lib/aspectjweaver-1.7.3.jar 
     * -Djava.ext.dirs=$currentdir/lib:config com.ximalaya.xdcs.alert.task.XdcsAlertTask
     * </pre>
     * 
     * <h1>-XX:MaxTenuringThreshold=15</h1> 用法: -XX:MaxTenuringThreshold=15。
     * 该参数主要是控制新生代需要经历多少次GC晋升到老年代中的最大阈值。 在JVM中用4个bit存储（放在对象头中），所以其最大值是15。
     * 但并非意味着，对象必须要经历15次YGC才会晋升到老年代中。例如，当survivor区空间不够时，便会提前进入到老年代中，但这个次数一定不大于设置的最大阈值。
     * <h1>-XX:TargetSurvivorRatio</h1> 那么JVM到底是如何来计算S区对象晋升到Old区的呢？ 首先介绍另一个重要的JVM参数：
     * -XX:TargetSurvivorRatio：一个计算期望s区存活大小(Desired survivor size)的参数。默认值为50，即50%。
     * 当一个S区中所有的age对象的大小如果大于等于Desired survivor
     * size，则重新计算threshold，以age和MaxTenuringThreshold两者的最小值为准。
     * 
     */
    void 启动参数();

}
